package com.chen.base.utils;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 执行系统命令工具类
 * todo windowns cmd命令
 * @author C.W
 * @date 2022/5/9 17:17
 * @desc bash工具
 */
@Slf4j
public class BashUtil {

    @SneakyThrows
    public static void execBatScript(String batFilePath, String... params){
        Assert.isTrue(StrUtil.isNotBlank(batFilePath) && batFilePath.contains(".bat"),
                "bat文件路径错误: " + batFilePath);
        File file = new File(batFilePath);
        Assert.isTrue(file.exists(), "bat文件不存在! ");

        // 脚本参数
        if (params != null && params.length > 0){
            StringBuilder builder = new StringBuilder(batFilePath);
            for (String param : params) {
                builder.append(" ").append(param);
            }
            batFilePath = builder.toString();
        }

        Process process = Runtime.getRuntime().exec(batFilePath);
        // 获取外部程序标准输出流
        AsyncUtil.runAsync(new OutputHandlerRunnable(process.getInputStream(), true));
        // 获取外部程序标准错误流
        AsyncUtil.runAsync(new OutputHandlerRunnable(process.getErrorStream(), true));

        process.waitFor();
        process.destroy();
    }

    /**
     * 执行命令
     *
     * @param command 命令
     * @param dir 进入目录
     */
    public static int execCommand(String dir, String command) throws Exception {
        List<String> commands = new ArrayList<>();
        for (String s : command.split(" ")) {
            if (StrUtil.isNotBlank(s)) {
                commands.add(s);
            }
        }

        ProcessBuilder process = new ProcessBuilder(commands.toArray(new String[0]));
        if (StrUtil.isNotBlank(dir)) {
            process.directory(new File(dir));
        }
        log.info("run command -> {} ", command);

        Process exec = process.start();
        // 获取外部程序标准输出流
        AsyncUtil.runAsync(new OutputHandlerRunnable(exec.getInputStream(), false));
        // 获取外部程序标准错误流
        AsyncUtil.runAsync(new OutputHandlerRunnable(exec.getErrorStream(), true));

        int code = exec.waitFor();
        log.info("command -> {} , result -> {}", command, code);
        return code;
    }

    private static class OutputHandlerRunnable implements Runnable {
        private final InputStream is;

        private final boolean error;

        public OutputHandlerRunnable(InputStream is, boolean error) {
            this.is = is;
            this.error = error;
        }

        @Override
        public void run() {
            try (BufferedReader br = new BufferedReader(new InputStreamReader(this.is))) {
                String line;
                while ((line = br.readLine()) != null) {
                    if (error) {
                        System.out.println(new String(
                                line.getBytes(StandardCharsets.UTF_8),
                                StandardCharsets.UTF_8)
                        );
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}